#! /usr/bin/env python

# Alunos:   Eliezer de Souza da Silva  RA: 124065
#           Fernanda Brandao Silva     RA: 060727
#           Michel Silva Fornaciali    RA: 071884
# IA368R: Eduardo Valle - Trabalho 3, Programa 3 - Processamento da consulta
#
# recebe como parametro um nome de um arquivo com uma base de descritores locais
# um numero n 
#
import sys
from operator import itemgetter
from numpy import array, dot, sqrt, argmin
from scipy.spatial.distance import cdist
import lshkit

def distEuclidiana(v,w):
    # Calcula a distancia euclidiana de dois vetores
    return sqrt(dot(v-w,v-w))
    
def strline2array(line,inicio,fim):
    # Dado uma linha do descritor da imagem, extrai o vetor de caracteristica e converte em array  
    # o parametro inicio e fim significa que os elementos entre um e outro serao convertidos para array.
    return array(line.split(" ")[inicio:fim], 'int')   # PARAMETRIZAR ESTES INDICES!
    

    
# --------- PROGRAMA PRINCIPAL ---------
    
print ">>> Inicio da leitura da imagem de consulta..."        
    
# Armazena os parametros de entrada
baseFile = sys.argv[1]          # arquivo da base
nImages = int(sys.argv[2])      # numero de imagens

# Leitura dos vetores de caracteristica da imagem de consulta
consulta = []
for vector in sys.stdin:
    consulta.append(strline2array(vector,4,132))
    
print "  > Fim da leitura da imagem de consulta!" 
print "  > Imagem com "+str(len(consulta))+" descritores!" 
print ">>> Inicio do processamento da base..."  
    
# Leitura do arquivo da base
f = open(baseFile)
    
# Processa a base armazenando os dados no formato "imagem, vetorCaracteristica" e tambem criando um indice de votos
base = []
invindex = []
votos = dict() 
for line in f:        
    aux = line.split(" ")
    base.append(strline2array(line,5,133))    # PARAMETRIZAR ESTES INDICES!
    votos[aux[0]]=0.0 #hashtable indexada pelo nome do arquivo
    invindex.append(aux[0]) #indice inverso que faz o mapeamento do indice na base para um nome na hashtable

f.close()    

print "  > Fim do processamento da base!"  


tBase = len(base)
total = tBase*len(consulta)
print ">>> Base com ", tBase, " descritores e ", len(votos), " imagens" 
print ">>> Inicio da contagem de votos: serao calculadas ", total, " distancias..."    

lsh = lshkit.LSH(10,20,5,50,5)
lsh.BuildHashIndex(base,20)
print("L= "+str(lsh.L)+" M="+str(lsh.M))
#base=array(base)
#consulta=array(consulta)
#distancias= cdist(consulta,base, 'euclidean')
menoresdist = [lsh.QueryIndex(c)[0] for c in consulta]
#votostemp  # para nao precisar ficar calculando o hash do voto multiplas vezes.
print(menoresdist)
for descindex in menoresdist:
    votos[invindex[descindex]]+=1

print "  > Fim da contagem dos votos!"
print ">>> Impressao dos resultados..."
  
# Ordena as imagens pelo numero de votos 
votos = sorted(votos.iteritems(), key=itemgetter(1), reverse=True)   


# Lista as N imagens mais votadas
k=0
for voto in votos:
    sys.stdout.write(str(voto[0]) + " " + str(voto[1]) + "\n")
    k+=1
    if(k>=nImages):
        break
    
